闲话 22.8.21

闲话

麻了
赛时突然死机了 关机重启好了 幸亏我保存了插件
赛后改题时又死机了 满心希望关机再开开就能好了
它 不 开 机 了
于是去jjdw和soytony那边待了一会儿
改了两个小时T3发现是字符型忘记减 '0' 了

今天延续前几天的春卷饭老歌传统
是《22世纪的我们》!
这首歌是春卷饭早期歌里我最喜欢的一首!
当我知道《两个人的》专辑里重制了这首歌时我高兴坏了

22世紀の僕らは

廃材と晴天 人間と雲
废材和与晴天 人类和云朵
昨日倒れた高層ビルには
昨日倒塌的高楼中
誰も居なくて
谁都已经不在了
瓦礫と火を片す人の影が見えない
收拾着瓦砾和火苗的人影亦无法看见
遠い時間がたったのさ
时间已经过去很久了啊

22世紀人類の旅
22世纪的人类的旅行
どろどろにされた正義の火葬は
腐化的正义的火葬
期待などされちゃいなくって
都逐渐不被期待了

大体僕らは
大概我们早就把活着这件事
生きる事を忘れすぎてて
忘得一干二净了吧
死んじゃう前の前の日くらいに
在迎接死亡的前几日
騒ぎ始める
才开始慌张起来

ごめんね僕も人の事なんて
抱歉呐 如果能评论人类的所为
言えてたらここに居ないさ
那我也不会身在此处了
枯れ木みたいに後悔の足で
后悔的双脚就如同枯死的树木
呆然と望郷の夜
出神地怀念着家乡的夜晚
遠いところへ行かなくちゃ
不得不去往遥远的地方了
こんな時間がたつ前に
在到了这种地步之前

22世紀人類はまた
22世纪的人类再次
からからになった背後のアイロニ
在幕后讽刺般地变得空虚起来
僕らここで死んでいったのさ
我们就在这里逝去啊
22世紀人類は未だ
22世纪的人类再次
黄昏なんて暗喩の違和感から
从黄昏的暗喻之中感到违和
逃げ出せず夢を見る
但仍在梦中无法逃离

廃材と晴天と人間と
废材和晴天和人类
なんだっけ
还有什么来着
ごめんね僕も人の事なんて
抱歉呐 如果能评论人类的所为
言えてたらここに居ないさ
那我也不会身在此处了
人形みたいな交差点だから
站在如同人偶一般的交叉路口
平然と最低なまま
于是就这样差劲地装着不在乎

22世紀人類は僕と
22世纪人类与我一同
22回の後悔をしても
22次感到懊悔也无济于事
22歳の父さんの指で
22岁的父亲用手指
22月のカレンダーをめくる
将22月的日历翻过
摩天楼が泣いた暗い夜
摩天楼哭泣的夜晚
バラバラにされた
被弄得七零八碎了
迷子のハーモニー
迷路的孩子们的和声
帰り道どこにもなくって
回去的道路怎么也找不到了
22世紀の僕らは
22世纪的我们

直到今天我还能唱出这首歌的大半部分这点足以说明我对这首歌的喜爱
饭早期的歌都是在不加修饰的合成乐器间的机械声线miku
这种我就挺喜欢的 总是能有一些别样的体会

最近一直在哼Aster 发现自己记不住太多词了

jjdw今天的闲话是《最炫民族风》(?)
开玩笑呢 其实是匹老板的《呐 呐 呐》
说到匹老板 匹老板的歌其实也挺不错的 很洗脑没问题
像是以前的《像神一样啊》,最近的《转生苹果》《余命2:30》
都是能给人带来很多思考的好歌

杂题

就……挺杂的

O(n) 约瑟夫

约瑟夫游戏改版。仍然是一个圈,以第一个报数的人为 \(1\),顺时针方向编号至 \(n\)。在第 \(i\) 轮需要报 \(i\) 个数字,报到第 \(i\) 个数的人出局。请输出最后一个存活人的编号。

\(n \le 10^7\)

注意到数据范围逼迫我们搞出一个线性做法。

考虑一个递推方法。在第一个人出圈后,剩余的人可以组成一个以出圈人下一位为 \(1\) 的新约瑟夫环,大小为 \(n-1\)。我们发现,新约瑟夫环内每个人的编号我们都可以 \(O(1)\) 地自原环编号转换而来。假设我们已经知道了这个约瑟夫环的解,那我们就可以 \(O(1)\) 地得到原问题的解。这显然递推解决。设 \(f_i\) 表示 \(i\) 个人进行约瑟夫游戏的胜者编号,则据定义有 \(f_i = (f_{i-1} + (n - i)) \% (i+1)\)。递推即可。

简单的代码
cin >> n, f[1] = 1;
for( int i = 2; i <= n; ++i ) f[i] = ( f[i-1] + (n-i+1) % i - 1 ) % i + 1;
cout << f[n] << "\n";

多项式优化点分治

定义对一棵多叉树的旋转操作如下:
当旋转点 \(x\) 时,若 \(x\) 的父亲为根,则将 \(x\) 作为根。反之,断开其父亲与祖父的边,链接其自己与祖父。
对于多次旋转,旋转点的深度不下降。

给定一棵 \(n\) 个节点的树,每个节点有非负权值 \(b\)。这棵树的每个节点上都有一个灯。每个单位时间亮起一个灯。第一个亮起的灯是根节点,在这之后随机亮起一个父亲的灯已亮但自己没有亮的灯。定义一个节点 \(x\) 的灯亮起的贡献如下:

\[\sum_{\text{y 为 x 的父祖先}} b[x] \times b[y] + \max(b[x], b[y]) \]

一棵树的总贡献即为各节点贡献之和。

请求出给定树在进行随机旋转后不同形态总贡献的期望。不同形态定义为两种旋转后的树,其中存在至少一个节点的父亲不同。

\(n \le 10^5, b[i] \le 10^4, \sum b[i] \le 10^5\)。为防止精度问题,答案对 \(1000000007\) 取模。

评价:什么sb题
这就是昨天闲话里出镜的那道题。

可以发现,旋转操作所生成的所有树都是原树的一种可能的点分治树,因为旋转就相当于改变对应点和它父亲点分治时的顺序。
在所有的树上按照题目规定发光,其实就是不断执行这个操作:在全局随机选一个点发光,以这个点计算所在联通块的答案,随后把这个点删掉。
因此类比点分治,我们发现选取一个点发光的实质是在树内随机选取一个分治中心,随后递归点亮其子树。由于题目要求点深度递增,容易发现可以在满足题目要求的情况下构造出任何一种点分治树。-By delov
考虑一对点对 \((x,y)\) 的贡献,当 \(x\)\(y\) 的祖先时 \(y\)\(x\) 有贡献当且仅当在 \(i\leftrightarrow j\) 的路径上 \(j\) 为第一个被删除的点。因为删别的点后两个点不连通了就。由于删除可能性随机,因此总答案可以被统计为

\[\sum_{i = 1}^n \sum_{j = 1}^n \frac{b[i]\times b[j] + \max(b[i],b[j])} {dis(i,j)+1} \]

进行一些基础的 \(\text{Min-Max}\) 容斥:

\[\begin{aligned} & a + b + \max(a, b) \\ =\ & a + b + ab + 1 - ab - 1 + \max(a,b) \\ =\ & a + b + ab + 1 - (ab - \max(a, b)) + 1 \\ =\ & (a + 1)(b + 1) - \min(a,b) + 1 \\ =\ & (a + 1)(b + 1) - \min(a + 1, b + 1) \end{aligned} \]

因此式子可以通过 \(b\) 整体 +1 转换为下式:

\[\sum_{i = 1}^n \sum_{j = 1}^n \frac{b[i]\times b[j] - \min(b[i],b[j])} {dis(i,j)+1} \]

考虑两部分分别求值。

相乘的前半部分

考虑点分治。对于以重心为根的每棵子树,统计子树内与子树外的点造成的贡献。构造两个多项式 \(A,B\),对于子树内的点 \(x\),在 \(A\) 的第 \(dis[x]\) 项加上 \(b[x]\)。对于子树外的点在 \(B\) 上施相同变换。多项式乘法,结果多项式的第 \(i\) 项的系数除 \(i+1\) 后求和即为答案。总时间复杂度 \(O(n \log^2n)\)

没错这个sb题是多项式加速但是不给NTT模数 而且它卡常 拿三次FFT都卡的要死也就是说别想用四次任意模NTT
这就逼着我们用FFT 但是《为防止精度问题》
调了一个多小时答案一直差一点 你告诉我是精度丢失

取min的后半部分

我们看到了一个神奇的条件:\(\sum b[i] \le 10^5\)。考虑怎么使用这个条件。

我们进行阈值分治。具体地,我们设定一个阈值 \(\text{T}\),对于 b 值不同的点分开处理。

  1. 我们记录 \(b > \text{T}\) 的点,随后朴素地匹配。我们首先预处理st表,随后 \(O(1)\) LCA加速dis求解。这样我们可以在最坏 \(O(\lfloor \frac {n}{\text{T}} \rfloor ^2 )\) 的复杂度下求得这部分点的结果。
  2. 对于 \(b \le \text{T}\) 的点,考虑差分求解。也就是说,我们可以用 \(\min \ge k\) 的点对数减去 \(\min \ge k+1\) 的点对数得到 \(\min = k\) 的点对数。
    仍然考虑点分治。若 \(\min(a,b) \ge k\) 则定有 \(a \ge k\ \land\ b\ge k\)。因此考虑多项式加速求解。对于给定 \(k\),我们考虑两个多项式 \(A,B\),对于子树内的点 \(x\),若 \(b[x] \ge k\),在 \(A\) 的第 \(dis[x]\) 项 +1。对于子树外的点在 \(B\) 上施相同变换。多项式乘法,结果多项式的第 \(i\) 项的系数即为 \(\min \ge k\),分母为 \(i+1\) 的对数。对于所有值求和后差分即可得到答案。

总时间复杂度为 \(O(\lfloor \frac {n}{\text{T}} \rfloor ^2 + (\text{T}+1)\times n \log^2n)\)

\(\text{T} = 15\) 左右可以通过本题 -By 题解

这奇怪的马蜂是题解 别指望我调这道题
#include <cstdio>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
typedef double db;
const int N=100500,mo=1e9+7,LM=16;
const db PI=acos(-1),ESP=3e-1;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
int a[N],Si[N],Cd[N];
int co[N],co1[N];
int B[2*N][2],A[N],B0;
int B1[LM+1][N];
LL Ans[N],ans;
struct FFTv
{
    db x,y;
    FFTv(db _x=0,db _y=0){x=_x;y=_y;}
    friend FFTv operator +(FFTv q,FFTv w){return FFTv(q.x+w.x,q.y+w.y);}
    friend FFTv operator -(FFTv q,FFTv w){return FFTv(q.x-w.x,q.y-w.y);}
    friend FFTv operator *(FFTv q,FFTv w){return FFTv(q.x*w.x-q.y*w.y,q.x*w.y+q.y*w.x);}
}g[N*4],g1[N*4],f[N*4],c[4*N];
FFTv Ww[262144/2+5];
int Ww0=262144/2;
bool z[N];
 
LL ksm(LL q,int w)
{
    LL ans=1;q%=mo;
    for(;w;w>>=1,q=q*q%mo)if(w&1)ans=ans*q%mo;
    return ans;
}
int eR[20][N*4];
void DFT(FFTv *a,int n,int ws,int K)
{
    fo(i,0,n-1)
    {
        if(!eR[ws][i])
        {
            register int q=0;
            for(register int j=i,k=n-1;k;k>>=1,j>>=1)q=(q<<1)+(j&1);
            eR[ws][i]=q;
        }
        c[eR[ws][i]]=a[i];
    }
    FFTv t;
    for(register int I=2;I<=n;I<<=1)
    {
        register int mid=I>>1;
        FFTv W=(K>0?Ww[Ww0/I]:Ww[Ww0-Ww0/I]);
        for(int j=0;j<n;j+=I)
        {
            FFTv w(1.0,0.0);
            fo(i,j,j+mid-1)
            {
                t.x=c[i+mid].x*w.x-c[i+mid].y*w.y;
                t.y=c[i+mid].x*w.y+c[i+mid].y*w.x;
                c[i+mid].x=c[i].x-t.x; c[i+mid].y=c[i].y-t.y;
                c[i].x=c[i].x+t.x; c[i].y=c[i].y+t.y;
                w=w*W;
            }
        }
    }
    if(K<0)fo(i,0,n-1)c[i].x=c[i].x/n;
}
void FFT1(FFTv *a,FFTv *ans,int n)
{
    int m=1,ws=1;
    for(;m<=n;m<<=1,++ws);
    m<<=1;
    fo(i,n+1,m)a[i].x=a[i].y=0;
    DFT(a,m,ws,1);
    fo(i,0,m-1)ans[i]=c[i]*c[i];
    DFT(ans,m,ws,-1);
    fo(i,0,m-1)ans[i]=c[i];
}
void FFT(int *a,int *b,FFTv *ans,int n)
{
    int m=1,ws=1;
    for(;m<=n;m<<=1,++ws);
    m<<=1;
    fo(i,0,n)g[i].x=a[i],g[i].y=b[i];
    fo(i,n+1,m)g[i].x=g[i].y=0;
    DFT(g,m,ws,1);
    register db ax,ay,bx,by;
    for(int i=0;i<m;++i)
    {
        register int j=(m-i)&(m-1);
        ax=(c[i].x+c[j].x)/2,ay=(c[i].y-c[j].y)/2;
        by=(c[j].x-c[i].x)/2,bx=(c[i].y+c[j].y)/2;
        ans[i].x=ax*bx-by*ay;
        ans[i].y=ax*by+ay*bx;
    }
    DFT(ans,m,ws,-1);
    fo(i,0,m-1)ans[i]=c[i];
}
 
void link(int q,int w)
{
    B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w;
    B[++B0][0]=A[w];A[w]=B0,B[B0][1]=q;
}
int zx,zx1,Alln;
int dfsf(int q,int fa)
{
    int mx=0;Si[q]=1;
    efo(i,q)if(!z[B[i][1]]&&B[i][1]!=fa)Si[q]+=dfsf(B[i][1],q),mx=max(mx,Si[B[i][1]]);
    mx=max(mx,Alln-Si[q]);
    if(zx1>mx)zx1=mx,zx=q;
    return Si[q];
}
int mxdp;
void dfs1(int q,int fa,int c)
{
    g[c].x+=a[q];mxdp=max(c,mxdp);
    efo(i,q)if(!z[B[i][1]]&&B[i][1]!=fa)dfs1(B[i][1],q,c+1);
}
void DoFirst(int q,int Alln,int K)
{
    fo(j,0,Alln)g[j].x=g[j].y=0;
    mxdp=0;dfs1(q,0,K<0);
    FFT1(g,f,mxdp);
    if(K<0)fo(j,0,mxdp*2)Ans[j]=(Ans[j]-(LL)(f[j].x+ESP))%mo;
    else fo(j,0,mxdp*2)Ans[j]=(Ans[j]+(LL)(f[j].x+ESP))%mo;
}
void dfs2(int q,int fa,int c)
{
    co[c]+=2;Cd[q]=c;mxdp=max(c,mxdp);
    if(a[q]<=LM)B1[a[q]][++B1[a[q]][0]]=q;
    efo(i,q)if(!z[B[i][1]]&&B[i][1]!=fa)dfs2(B[i][1],q,c+1);
}
void DoMin(int q,int Alln,int K)
{
    fo(i,0,Alln)co[i]=0;
    mxdp=0;dfs2(q,0,K<0);
    fo(I,1,LM)if(B1[I][0])
    {
        fo(i,1,B1[I][0])co1[Cd[B1[I][i]]]+=a[B1[I][i]],--co[Cd[B1[I][i]]];
        FFT(co,co1,f,mxdp);
        if(K>0)fo(j,0,mxdp*2)Ans[j]=(Ans[j]-(LL)(f[j].x+ESP))%mo;
        else fo(j,0,mxdp*2)Ans[j]=(Ans[j]+(LL)(f[j].x+ESP))%mo;
        fo(i,1,B1[I][0])co1[Cd[B1[I][i]]]=0,--co[Cd[B1[I][i]]];
        B1[I][0]=0;
    }
}
int d[N],aR[N],cdp[N];
void dfsM(int q,int fa,int c,int R)
{
    if(a[q]>LM)
    {
        aR[q]=R,cdp[q]=c;
        fo(i,1,d[0])if(aR[d[i]]!=aR[q])(Ans[cdp[d[i]]+cdp[q]]-=2LL*min(a[q],a[d[i]]))<=-mo?Ans[cdp[d[i]]+cdp[q]]+=mo:0;
        else break;
    }
    efo(i,q)if(B[i][1]!=fa&&!z[B[i][1]])dfsM(B[i][1],q,c+1,R);
    if(a[q]>LM)d[++d[0]]=q;
}
void divide(int q)
{
    zx1=1e9;dfsf(q,0);
    z[q=zx]=1;
    int t=1;
    efo(i,q)if(!z[B[i][1]]&&Si[B[i][1]]<Si[q])t+=Si[B[i][1]];
    efo(i,q)if(!z[B[i][1]]&&Si[B[i][1]]>Si[q])Si[B[i][1]]=Alln-t;
    Si[q]=Alln;
    DoFirst(q,Alln,1);
    efo(i,q)if(!z[B[i][1]])DoFirst(B[i][1],Si[B[i][1]],-1);
    DoMin(q,Alln,1);
    efo(i,q)if(!z[B[i][1]])DoMin(B[i][1],Si[B[i][1]],-1);
    d[0]=0;if(a[q]>LM)d[0]=1,d[1]=q,aR[q]=0,cdp[q]=0;
    efo(i,q)if(!z[B[i][1]])dfsM(B[i][1],q,1,B[i][1]);
    efo(i,q)if(!z[B[i][1]])Alln=Si[B[i][1]],divide(B[i][1]);
}
int main()
{
    int q,w;
    fo(i,0,Ww0)Ww[i]=FFTv(cos(2*PI*i/Ww0),sin(2*PI*i/Ww0));
    read(n);
    fo(i,1,n)a[i]=read(q)+1;
    fo(i,1,n-1)read(q),read(w),link(q,w);
    Alln=n;divide(1);
    fo(i,1,n)if(a[i]>LM)Ans[0]-=a[i];
    Ans[0]%=mo;
    ans=0;
    fo(i,0,n-1)ans=(ans+Ans[i]*ksm(i+1,mo-2))%mo;
    printf("%lld\n",(ans+mo)%mo);
    return 0;
}
这是我第一次觉得delov的马蜂赏心悦目 delov的做法是我讲的这种做法 题解我看不懂
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define cp complex<double>
#define fir first
#define sec second
using namespace std;

const int maxn=1e5+10,Mod=1e9+7;
const double Pi= acos(-1);


#define gc if(++ip==ie)fread(ip=buf,1,SZ,stdin)
const int SZ=1<<19;char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int read(){ gc;while(*ip<'-')gc; bool f=*ip=='-';if(f)gc; int x=*ip&15;gc; while(*ip>'-'){x*=10;x+=*ip&15;gc;} return f ? -x : x; }
int pw(int x,int p){int res=1,base=x;while(p){if(p&1)res=1LL*res*base%Mod;base=1LL*base*base%Mod;p>>=1;}return res;}
int Inv(int x){return pw(x,Mod-2);}

cp W[maxn],Cw[maxn];
int rev[maxn];
int deg,lg;
int inv[maxn];

cp Ome(int n,int k){return cp(cos(Pi*2*k/n),sin(Pi*2*k/n));}

void Init(int len){ 
	deg=1,lg=0;while(deg<len)deg<<=1,++lg;
	for(int i=0;i<deg;++i)rev[i]=((rev[i>>1]>>1)|((i&1)<<(lg-1))),
	W[i]=Ome(deg,i),Cw[i]=conj(W[i]); 
}
struct Poly{	
	vector<cp>f;
	cp &operator[](const int &i){return f[i];}
	cp operator[](const int &i)const{return f[i];}
	int Deg(){return f.size();}
	int Deg()const{return f.size();}
	void Set(int len){f.resize(len);}
	void Print(){for(auto it : f)cerr<<it<<" ";cerr<<"\n";}
	int Sum(){int res=0;for(int i=0;i<f.size();++i)res=(0LL+res+((ll)f[i].real())%Mod*inv[i+1]%Mod)%Mod;return res;}
	void FFT(int deg,cp w[],int opt){
		Set(deg);for(int i=0;i<deg;++i)if(i<rev[i])swap(f[i],f[rev[i]]);
		for(int t=deg>>1,m=1;m<deg;m<<=1,t>>=1)for(int i=0;i<deg;i+=(m<<1))for(int j=0;j<m;++j)
		{ cp x=f[i+j],y=w[t*j]*f[i+j+m];f[i+j]=x+y,f[i+j+m]=x-y;}
		if(opt==-1){ for(int i=0;i<deg;++i)f[i].real(f[i].real()/deg+0.5); }
	}
	friend Poly operator * (const Poly &x,const Poly &y){
		Poly res,A=x,B=y;
		Init(A.Deg()+B.Deg()-1);
		A.FFT(deg,W,1);B.FFT(deg,W,1);res.Set(deg);
		for(int i=0;i<deg;++i)res[i]=A[i]*B[i];
		res.FFT(deg,Cw,-1);
		return res;
	}
	void operator *= (const Poly &x){
		Poly A=x;
		Init(Deg()+A.Deg()-1);
		FFT(deg,W,1),A.FFT(deg,W,1);
		for(int i=0;i<deg;++i)f[i]=f[i]*A[i];
		FFT(deg,Cw,-1);
	}
	void operator += (const Poly &x){
		Set(max(Deg(),x.Deg()));
		for(int i=0;i<x.Deg();++i)f[i]=f[i]+x[i];
	}

};
int n,m;
int ans;int b[maxn];
int K;int C[maxn];

int st[maxn*4][20],rec[maxn*4][20];
int Ca[maxn*2];
int Lg[maxn*4];

vector<int>son[maxn];

int RTT;

struct Graph{
	struct eg{int from,to,next;}e[maxn*2];
	int len,head[maxn];int ass;
	void lqx(int from,int to)
	{ e[++len].from=from,e[len].to=to,e[len].next=head[from],head[from]=len; }
	int dp[maxn],siz[maxn],root,sum;bool vis[maxn];
	int Te,dfn[maxn*4],ver[maxn*4],R[maxn*4],depth[maxn];
	void Dfs(int u,int dep){
		dfn[u]=++Te;ver[Te]=u;R[Te]=dep;
		depth[u]=dep;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;
			if(!dfn[v]){
				Dfs(v,dep+1),ver[++Te]=u,R[Te]=dep;
			}
		}
	}
	void Init(){
		Lg[1]=0;st[1][0]=R[1],rec[1][0]=ver[1];
		Rep(i,2,Te)st[i][0]=R[i],rec[i][0]=ver[i],Lg[i]=Lg[i>>1]+1;
		Rep(j,1,__lg(Te))
			for(int i=1;i+(1<<j)-1<=Te;++i)
			if(st[i][j-1]<st[i+(1<<(j-1))][j-1])st[i][j]=st[i][j-1],rec[i][j]=rec[i][j-1];
			else st[i][j]=st[i+(1<<(j-1))][j-1],rec[i][j]=rec[i+(1<<(j-1))][j-1];
	}
	void Root(int u,int f){
		dp[u]=0,siz[u]=1;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==f || vis[v])continue;
			Root(v,u);siz[u]+=siz[v];dp[u]=max(dp[u],siz[v]);
		}
		dp[u]=max(dp[u],sum-siz[u]);if(!root || dp[u]<dp[root])root=u;
	}
	int mxdep,buc[maxn];
	void Dis(int u,int f,int dep){
		mxdep=max(mxdep,dep);buc[dep]=buc[dep]+b[u];
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==f || vis[v])continue;
			Dis(v,u,dep+1);
		}
	}
	Poly now,x;
	void Sol(int u){
		vis[u]=true;now.Set(1);now[0]=cp{(double)b[u],0};
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(vis[v])continue;
			mxdep=0;x.Set(0);Dis(v,u,1);x.Set(mxdep+1);
			Rep(j,1,mxdep)x[j]+=cp{(double)buc[j],0},buc[j]=0;
			ans=(ans+(now*x).Sum())%Mod;
			now+=x;
		}
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(vis[v])continue;
			root=0,sum=siz[u];Root(v,u),Root(root,0);
			son[u].push_back(root);
			Sol(root);
		}
	}
	void Dep(int u,int f,int dep){
		mxdep=max(mxdep,dep);buc[dep]+=(b[u]>=K);
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==f || vis[v])continue;
			Dep(v,u,dep+1);
		}
	}
	void Calc(int u){
		vis[u]=true;now.Set(1);
		if(b[u]>=K)now[0]=cp{1,0};
		else now[0]=cp{0,0};
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(vis[v])continue;
			mxdep=0;x.Set(0);Dep(v,u,1);x.Set(mxdep+1);
			Rep(j,1,mxdep)x[j]+=cp{(double)buc[j],0},buc[j]=0;
			ass=(ass+(now*x).Sum())%Mod;
			now+=x;
		}
		for(auto v : son[u])Calc(v);
	}
	int Work(){
		ass=0;memset(vis,0,sizeof(vis));
		Calc(RTT);
		return ass;
	}
	int Lca(int u,int v){
		u=dfn[u],v=dfn[v];
		if(u>v)swap(u,v);
		int k=Lg[v-u+1];
		if(st[u][k]<st[v-(1<<k)+1][k])return rec[u][k];
		else return rec[v-(1<<k)+1][k];
	}
	int DIS(int u,int v){ return depth[u]+depth[v]-2*depth[Lca(u,v)]; }
}G;

vector<pii>vec;

void solve(){ 
	fre(T4);
	int mx=0;
	n=read();Rep(i,1,n){b[i]=read();++b[i];mx=max(mx,b[i]);++Ca[b[i]];}int x,y;
	inv[0]=1;inv[1]=1;Rep(i,2,n+1)inv[i]=1LL*(Mod-Mod/i)*inv[Mod%i]%Mod;
	Rep(i,2,n)x=read(),y=read(),G.lqx(x,y),G.lqx(y,x);
	G.Dfs(1,1);G.Init();
	G.sum=n;G.Root(1,0),G.Root(G.root,0);RTT=G.root;G.Sol(G.root);ans=2LL*ans%Mod;
	int Ck=0;
	Dwn(i,mx,1){ Ca[i]+=Ca[i+1]; if(Ca[i]<=10000)Ck=i; }
	Rep(i,1,n){
		ans=(ans+1LL*b[i]*b[i])%Mod;
		if(b[i]>=Ck)vec.emplace_back(b[i],i);
	}
	Rep(k,1,Ck){ K=k; C[k]=(2LL*G.Work()%Mod+Ca[k])%Mod; }
	for(int k=1;k<Ck;++k){ ans=(ans-1LL*(C[k]-C[k+1])*k%Mod)%Mod;/*cerr<<C[k]<<"\n";*/ }
	for(auto it : vec)for(auto ip : vec)ans=(ans-1LL*min(it.fir,ip.fir)*inv[G.DIS(it.sec,ip.sec)+1])%Mod;
	printf("%d\n",(ans%Mod+Mod)%Mod);
}
posted @ 2022-08-21 20:55  joke3579  阅读(120)  评论(1编辑  收藏  举报